home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: Alpha / Whiteline Alpha.iso / progtool / pascal / o_gem / doku / doku.txt < prev    next >
Encoding:
Text File  |  1994-09-22  |  49.7 KB  |  1,403 lines

  1. WICHTIG: Diese Doku wurde aus einem TEX-File erzeugt. Leider hat dabei
  2. die Darstellungsqualität etwas gelitten :-), ich werde mich aber bei
  3. zukünftigen Versionen um ein besseres optisches Outfit kümmern.
  4. Aber es gibt ja mittlerweile auch das  g e d r u c k t e  Handbuch...
  5.  
  6.  
  7. Das
  8. ObjectGEM
  9. Programmierhandbuch
  10. Version 1.17
  11.  
  12.  
  13. Das vorliegende Handbuch ist urheberrechtlich geschützt. Alle Rechte vorbehalten.
  14. Jegliche Vervielfältigung auf fotografischem, mechanischem, elektronischem oder
  15. anderem Wege bedarf der schriftlichen Genehmigung durch den Autor.
  16.  
  17. Die in diesem Buch erwähnten Markenzeichen, Firmennamen, Software- und
  18. Hardwareprodukte sind nicht gesondert gekennzeichnet, unterliegen aber
  19. trotzdem dem jeweiligen gesetzlichen Schutz.
  20.  
  21. ObjectGEM und Dokumentation Copyright 1992-94 Thomas Much
  22. "ObjectGEM in Beispielen" Copyright 1994 Jan Pilgenröder @ AC3
  23.  
  24.  
  25.  
  26. Auf dem Atari ST/STE/TT/Falcon bricht ein neues Zeitalter des Software-Engineering
  27. an! Aber sehen und lesen Sie selbst...
  28.  
  29. ObjectGEM ist eine Sammlung von Units für PurePascal, mit der komplexe GEM-Programme
  30. wesentlich einfacher als bisher erstellt werden können. Mit ObjectGEM wird es auch möglich, daß
  31. alle Programme, die z.Z. auf GEM verzichten, weil sie z.B. nur irgendwelche Statusausgaben machen,
  32. korrekt und mit nur geringem Mehraufwand unter GEM implementiert werden. Außerdem
  33. können Dialoge mit allen State-of-the-Art-Buttons etc. versehen werden, der Rest (Verwaltung,
  34. Redraw, Auswertung) geschieht dann automatisch. Wer allerdings unbedingt möchte, kann sich auch
  35. bis zur untersten Stufe der GEM-Programmierung mit einklinken - OOP macht's möglich!
  36. ObjectGEM-Programme sind im Vergleich zu anderen Bibliotheken recht groß. Dabei muß man
  37. aber die Tatsache bedenken, daß objektorientierte Programmierung eigentlich noch nie auf den
  38. Speicherbedarf geachtet hat (das liegt in der Natur der Sache...). Dafür ist der Funktionsumfang aber
  39. beträchtlich, denn selbst das kleinste ObjectGEM-Programm weiß bereits, wie ein komplettes
  40. GEM-Fenster zu funktionieren hat. Außerdem kommt es in der heutigen Zeit mehr darauf an, in möglichst
  41. kurzer Zeit Programme zu schreiben, die leicht zu bedienen sind, sicher laufen und gut erweitert
  42. bzw. gewartet werden können; der Speicherbedarf tritt dabei zunehmend in den Hintergrund.
  43. Trotzdem belegt ObjectGEM immer nur soviel Speicher wie gerade nötig, da so ziemlich alles dynamisch
  44. verwaltet wird. Und außerdem: Wer einmal mit ObjectGEM angefangen hat, wird bestimmt nicht so
  45. schnell wieder damit aufhören!
  46. ObjectGEM ist an neuere AES-Versionen (4.x), MultiTOS und Mag!C angepaßt, d.h. es ist z.B.
  47. möglich, Dialoge im Hintergrund zu bedienen (Buttons anklicken etc.)! Für X/Unix-Benutzer steht
  48. sogar ein entsprechender Mausposition-abhängiger Eingabemodus zur Verfügung. In Vorbereitung
  49. ist außerdem der GEM-Wizard, mit dem ObjectGEM-Programme mit ein paar Mausklicks generiert
  50. werden können!
  51.  
  52. für Atari ST, STE, TT, Falcon mit PurePascal, mind. 1 MB RAM und Festplatte
  53. Shareware, daher nur DM 50,- Registrierungsgebühr (DM 60,- incl. Handbuch)
  54. incl. aller Quelltexte
  55. autom. Dialogabarbeitung (optional auch "von Hand")
  56. ebenso einfache Behandlung von Fenstern und Menüs
  57. Fensterdialoge (auch im Hintergrund bedienbar!)
  58. Fenster-Toolbars und -Menüs unter allen TOS-Versionen
  59. automatische XAcc- und AV-Protokoll-Behandlung
  60. Iconification (auch ICFS), Drag&Drop
  61. kontextsensitive Bubble-Help (s. Mac System 7)
  62. ausführliche Online-Hilfe innerhalb der PP-Shell
  63.  
  64. Und wen es interessiert: Ein Test von ObjectGEM 1.00 findet sich im ST-Magazin 
  65. 7/93, S.22 ff.!
  66.  
  67. Nun aber genug der Vorrede, viel Spaß und Erfolg mit ObjectGEM!
  68.  
  69. ObjectGEM ist ein Shareware-Produkt. Das Programmpaket darf beliebig 
  70. weitergegeben werden, sofern die Units (d.h. die Quelltexte mit den 
  71. dazugehörigen Dateien (Beispielprogramme, Dokumentation etc.) zusammen
  72. weitergegeben werden. Jeder kann dann in Ruhe ein bißchen mit ObjectGEM 
  73. herumprobieren. Wer allerdings länger mit ObjectGEM programmiert (egal, ob die 
  74. Programme veröffentlicht werden oder nicht), muß sich registrieren lassen.
  75.  
  76. Die Registrierung kostet DM 50,- (bzw. DM 60,- mit Handbuch). Das ist -
  77. im Vergleich zu kommerziell angebotenen Bibliotheken - nicht sehr viel.
  78. Trotzdem dürfen Programme, die mit 
  79. einer registrierten ObjectGEM-Version erstellt wurden, ohne etwaige 
  80. Lizenzgebühren weitergegeben, verkauft etc. werden.
  81.  
  82. Überweisen Sie dazu DM 50,- (bzw. DM 60,-) auf das Konto:
  83.  
  84.  
  85. Thomas Much, Sparkasse Karlsruhe,
  86.  
  87. Kto. 935 30 95, BLZ 660 501 01
  88.  
  89. (Ihre Adresse nicht vergessen!)
  90.  
  91.  
  92. oder schicken sie einen Verrechnungsscheck über diesen Betrag an:
  93.  
  94.  
  95. Softdesign Computer Software
  96.  
  97. c/o Thomas Much, Gerwigstraße 46, 76131 Karlsruhe
  98.  
  99.  
  100. Sie können den Betrag auch auf folgendes Konto überweisen:
  101.  
  102.  
  103. Thomas Much, Postgiroamt Karlsruhe,
  104.  
  105. Kto. 314881-753, BLZ 660 100 75
  106.  
  107.  
  108. Dann muß allerdings mit z.Z. bis zu vier Wochen Wartezeit gerechnet werden (die 
  109. Post...). Wichtig: Wenn Sie einen Scheck aus dem Ausland schicken und diesen 
  110. nicht in DM ausstellen, berechnen Sie bitte DM 8,- extra! Wenn Sie aus dem 
  111. Ausland überweisen, machen Sie dies bitte so, daß der Empfänger keine 
  112. zusätzlichen Gebühren zahlen muß. Danke!
  113.  
  114. Sie erhalten dann umgehend die aktuelle Version - es sei denn, Sie geben bei 
  115. Ihrer Registrierung die Versionsnummer der Ihnen vorliegenden ObjectGEM-Unit 
  116. an; ist diese Version noch aktuell, erhalten Sie erst dann eine Diskette
  117. zugeschickt, wenn eine neue Version veröffentlicht wird (wer also auf jeden 
  118. Fall und sofort eine Disk bekommen möchte, sollte bei seiner Registrierung 
  119. keine Versionsnummer angeben...). Außerdem haben Sie dann die Möglichkeit, 
  120. jederzeit mit einer formatierten 3,5" Diskette und einem frankierten und 
  121. addressierten Rückumschlag ein evtl. vorhandenes ObjectGEM-Update direkt beim 
  122. Autor (Adresse s.u.) zu bekommen. Kosten wird dies nur dann etwas, wenn der 
  123. Registrierpreis steigen sollte. Die neueste Version ist aber auch per Modem 
  124. über die Maus-Mailboxen KA, AC3 und HL zu beziehen (und vermutlich auch in
  125. einigen anderen Mailboxen erhältlich).
  126.  
  127. Der Vertrieb über PD-Versender, Mailboxen, Diskettenzeitschriften etc. ist 
  128. erlaubt und ausdrücklich erwünscht! Dann möge man sich aber bitte um die
  129. aktuelle Version bemühen.
  130.  
  131. Achtung: Zusammen mit ObjectGEM darf der VDI-Enhancer weitergegeben werden. 
  132. PD-Versender müssen vor der Weitergabe aber erst prüfen, ob sie die entsprechenden
  133. Bedingungen erfüllen. Ist dies nicht der Fall, müssen sie den Enhancer 
  134. aus dem ObjectGEM-Paket entfernen!
  135.  
  136. Da ObjectGEM mit dem vollständigen Quelltext ausgeliefert wird, hat die 
  137. Shareware-Version keinerlei Einschränkungen mehr. Ich hoffe aber trotzdem, daß
  138. sich dies nicht negativ auf die Registrierungsmoral auswirkt - ich würde mich 
  139. freuen, wenn alle diejenigen, die sich bisher wegen PP-Kompatibilitätsproblemen
  140. oder dem fehlenden Quelltext nicht registrieren lassen wollten (dies 
  141. wurde mir von sehr vielen Leuten mitgeteilt), nun die Weiterentwicklung 
  142. finanziell unterstützen würden.
  143.  
  144. Die registrierte Vollversion von ObjectGEM ist incl. Handbuch für DM 60,-
  145. auch bei whiteline erhältlich:
  146.  
  147.  
  148. whiteline Konzeption, delta labs software
  149.  
  150. B. Artz & T. Kohl, Rembrandtstraße 1, 42329 Wuppertal
  151.  
  152. Tel. & Fax (0202) 734361
  153.  
  154. Kontakt im MausNet: Tom Kohl @ W
  155.  
  156.  
  157. Wichtig: Wer ObjectGEM mehr als nur zu Testzwecken einsetzt und sich nicht
  158. registrieren läßt, verwendet eine Raubkopie!!!
  159.  
  160.  
  161. Die Installation sollte keine großen Probleme bereiten. Kopieren Sie einfach 
  162. alle Pascal-Dateien (*.PAS) in Ihr Unit-Verzeichnis (dort, wo auch TOS.PPU,
  163. GEM.PPU etc. stehen) bzw. in das Verzeichnis, in dem Sie sonst die Quelltexte
  164. Ihrer Units ablegen, und GOBJECTS.HLP in das Help-Verzeichnis (dort sollten
  165. auch PP.HLP etc. zu finden sein). Fertig!
  166.  
  167. Die Units werden nun wie gewohnt mit der -Klausel eingebunden. Wenn Sie 
  168. Ihr erstes ObjectGEM-Programm compilieren, werden dann zunächst alle ObjectGem-
  169. Units erzeugt (das dauert etwas).
  170.  
  171. Um in die Übersicht der Online-Hilfe zu gelangen, suchen Sie unter "Help - 
  172. Help..." (oder mit ) am besten nach "ObjectGEM" oder 
  173. "GObjects". Ansonsten bringen Sie den Cursor auf eine fragliche Konstante 
  174. oder Methode und drücken , woraufhin eine Erklärung dazu erscheinen sollte. 
  175. Dabei ist es egal, ob Sie z.B. nach "Style" oder "Attr.Style" suchen - wenn 
  176. es mehrere Möglichkeiten gibt, erhalten Sie ein Auswahlmenü.
  177.  
  178. Wenn Sie meinen, einen Fehler in der Online-Hilfe gefunden zu haben (falscher 
  179. oder fehlender Verweis, falsche oder nicht ausreichende Beschreibung), setzen 
  180. Sie sich bitte mit mir (dem Autor) in Verbindung. Danke.
  181.  
  182. Falls Probleme mit oder Fragen zu ObjectGEM auftauchen sollten, können Sie dies 
  183. dem Autor direkt mitteilen. Bitte benutzen Sie den telefonischen Weg nur in 
  184. dringend Fällen oder bei kurzen Fragen. Wenn Sie ausführlichere Antworten 
  185. wünschen, schicken Sie bitten einen Brief mit folgenden zusätzlichen Angaben:
  186.  
  187. ObjectGEM-Version
  188. PurePascal-Version bzw. -Datum
  189. Rechner, Speicherausbau, Grafikkarte
  190. TOS-Version
  191.  
  192. (Übrigens: Da ObjectGEM Shareware ist, ist bei solchen Anfragen gegen 
  193. beiliegendes Rückporto nichts einzuwenden...)
  194. [3mm]
  195.  
  196. Softdesign Computer Software
  197.  
  198. c/o Thomas Much, Gerwigstraße 46, 76131 Karlsruhe
  199.  
  200. Tel.: (0721) 62 28 41 (am besten Mo-So zwischen 19 und 22 Uhr)
  201. [3mm]
  202.  
  203. Am liebsten werden natürlich Anfragen von registrierten ObjectGEM-Anwendern
  204. beantwortet, aber falls grundsätzliche Fragen bestehen, haben auch potentielle
  205. Käufer eine Chance (da Sie dies aber offensichtlich in gedruckter Form lesen,
  206. werden Sie höchstwahrscheinlich auch registriert sein).
  207.  
  208. Als registrierter Anwender haben Sie außerdem die Möglichkeit, Updates (die 
  209. alle paar Wochen erscheinen) durch Einsenden einer formatierten 3,5"-Diskette 
  210. und eines frankierten und addressierten Rückumschlags zu erhalten. Wenn Sie 
  211. dies "präventiv" machen (d.h. am besten sofort wieder nach Erhalt eines 
  212. Updates), bekommen Sie das nächste Update zugeschickt, sobald es verfügbar ist. 
  213. Und wenn Sie sowieso schon dabei sind, eine Update-Diskette einzuschicken, 
  214. wäre es nett, wenn Sie dann auch das Anwenderprofil ausdrucken (Datei REGISTR.TXT),
  215. ausfüllen und mitschicken könnten (besten Dank im vorraus!).
  216.  
  217. Wer ein Modem besitzt, kann sich natürlich die neuesten Versionen selbst saugen 
  218. (und kann damit auf die Diskette verzichten). Neue Versionen sind zuerst in 
  219. den Maus-Mailboxen KA und AC3 sowie in der ASH-Mailbox verfügbar. Das Anwenderprofil kann dann auch an die 
  220. folgende EMail-Adresse geschickt werden:
  221. [3mm]
  222.  
  223. MausNet: Thomas Much @ KA2oder
  224. [3mm]
  225. Internet: UK48@ibm3090.rz.uni-karlsruhe.de
  226. [4mm]
  227.  
  228. Maus KA, (0721) 358887, kein Gastdownload von 18.00 bis 21.45
  229.  
  230. Maus AC3, (0241) 54540, kein Gastdownload!
  231.  
  232. ASH-Mailbox, (06221) 303671
  233.  
  234. (dort jeweils die Datei GOBJ_1xx.ZIP im öffentlichen Programmteil)
  235. [3mm]
  236.  
  237. Außerdem ist ObjectGEM auf folgenden ftp-Sites zu finden:
  238.  
  239.  
  240. ftp.uni-muenster.de /pub/atari/Programming/gobj_1xx.zip
  241.  
  242. ftp.uni-kl.de /pub/atari/programming/gobj_1xx.zip
  243.  
  244. Diese Einführung soll zeigen, wie man mit ObjectGEM schnell und einfach eigene 
  245. GEM-Programme schreiben kann. Ich gehe dabei nicht allzusehr in die Tiefe und 
  246. ich werde auch nicht jeden einzelnen Befehl beschreiben (wer näheres zu den 
  247. einzelnen Befehlen wissen will, möge einen Blick in die Online-Hilfe werfen - 
  248. die Online-Hilfe ist wirklich gut und beschreibt jeden Befehl in aller 
  249. Ausführlichkeit.
  250. Stattdessen werde ich versuchen, zu zeigen, wie man die einzelnen Befehle 
  251. zusammenfügt.
  252.  
  253. Diejenigen, die mit den Grundbegriffen der GEM-Programmierung und der 
  254. objektorientierten Programmierung nicht vertraut sind, sollten sich jetzt 
  255. erst einmal schlau machen - diese Einführung kann die Grundlagen nicht 
  256. liefern. Das PurePascal-Handbuch sollte aber ausreichen, um das nötige Wissen 
  257. zu vermitteln.
  258.  
  259. Es gibt einige Elemente, die in jedem ObjectGEM-Programm vorkommen müssen. 
  260. Schauen wir uns dazu mal das kleinstmögliche Programm an:
  261.  
  262. PROGRAM Minimal;
  263.  
  264. USES
  265.  
  266. OWindows;
  267.  
  268. VAR
  269.  
  270. MyApplication: TApplication;
  271.  
  272. BEGIN
  273. MyApplication.Init('MINI','Minimal');
  274. MyApplication.Run;
  275. MyApplication.Done
  276. END.
  277.  
  278. Zunächstmal müssen wir die Unit OWindows benutzen. In dieser Unit stehen die 
  279. wichtigsten Objekte und Methoden (eine Liste findet sich in der Online-Hilfe). 
  280. Dann müssen wir unser Applikations-Objekt, das für die Initialisierung und den 
  281. Message-Loop des Programms zuständig ist, anlegen. Wir definieren eine 
  282. Variable MyApplication als Object vom Typ TApplication und initialisieren diese 
  283. Instanz von TApplication mit . Dabei ist 
  284. 'MINI' der Cookie, der beim Programmstart im Cookie-Jar eingetragen wird,
  285. und 'Minimal' der Name der Applikation.
  286.  
  287. kümmert sich dann um die Routienearbeit, während das Programm 
  288. läuft, und beendet das Programm.
  289.  
  290. Dieses Minimal-Programm kann sogar schon einiges. Es baut ein Fenster auf und 
  291. verwaltet es - man kann also mit diesem Fenster alles machen, was man so von 
  292. Fenstern gewohnt ist. Das Programm wird beendet, wenn man drückt
  293. oder das Fenster schließt.
  294.  
  295. Mit dem Fenster aus MINIMAL.PAS kann man allerdings noch nicht viel Sinnvolles 
  296. anfangen, und manchmal möchte man in seinem Programm überhaupt kein Fenster 
  297. (oder kein Haupt-Fenster) haben. Wenn wir an diesem Fenster etwas ändern wollen, 
  298. müssen wir dazu die Methode, die es anlegt, überschreiben. Diese Methode heißt 
  299. und ist eine Methode des Objektes TApplication; sie wird 
  300. innerhalb von TApplication.Init aufgerufen. Dazu legen wir uns ein von 
  301. TApplication abgeleitetes Objekt an, indem wir die Methode InitMainWindow
  302. neu schreiben. Das ganze sieht dann so aus:
  303.  
  304. PROGRAMM Minimal;
  305.  
  306. TYPE
  307.  
  308. PMyApplication = ^TMyApplication;
  309. TMyApplication = OBJECT(TApplication)
  310. PROCEDURE InitMainWindow; VIRTUAL;
  311. END;
  312.  
  313. VAR
  314.  
  315. MyApplication: TMyApplication;
  316.  
  317. PROCEDURE TMyApplication.InitMainWindow;
  318.  
  319. BEGIN
  320. END;
  321.  
  322. BEGIN
  323. MyApplication.Init('MINI','Minimal');
  324. MyApplication.Run;
  325. MyApplication.Done
  326. END.
  327.  
  328. Anstatt ein Fenster anzulegen, macht unser neues InitMainWindow einfach 
  329. gar nichts.
  330.  
  331. Dialoge und Alert-Boxen kommen nun wirklich in fast jedem GEM-Programm vor, 
  332. deshalb möchte ich auch gleich damit anfangen. Dazu dann auch gleich wieder 
  333. ein Beispiel:
  334.  
  335. PROGRAM Kleines;
  336.  
  337. USES
  338.  
  339. OWindows,OTypes,ODialogs;
  340.  
  341. I KLEINES.I
  342.     
  343. TYPE
  344.  
  345. TMyApplication = OBJECT(TApplication)
  346. PROCEDURE InitInstance; VIRTUAL;
  347. PROCEDURE InitMainWindow; VIRTUAL;
  348. END;
  349.  
  350. PInfoMenu = ^TInfoMenu;
  351. TInfoMenu = OBJECT(TKeyMenu)
  352. PROCEDURE Work; VIRTUAL;
  353. END;
  354.  
  355. POpenDialog = ^TOpenDialog;
  356. TOpenDialog = OBJECT(TKeyMenu)
  357. PROCEDURE Work; VIRTUAL;
  358. END;
  359.  
  360. PMyDialog =    ^TMyDialog;
  361. TMyDialog =    OBJECT(TDialog)
  362. FUNCTION OK: BOOLEAN; VIRTUAL;
  363. FUNCTION Cancel: BOOLEAN; VIRTUAL;
  364. END;
  365.  
  366. VAR
  367.  
  368. MyApplication: TMyApplication;
  369. Buffer : RECORD
  370. Kette: STRING[21];
  371. O1,O2: INTEGER
  372. END;
  373.  
  374. PROCEDURE TMyApplication.InitInstance;
  375.  
  376. BEGIN
  377. LoadResource('KLEINES.RSC','');
  378. LoadMenu(main_menu);
  379. NEW(PInfoMenu,Init(@SELF,K_Ctrl,Ctrl_I,
  380. menu_info,desk_menu));
  381. NEW(POpenDialog,Init(@SELF,K_Ctrl,Ctrl_D,
  382. menu_open_dialog,file_menu));
  383. INHERITED InitInstance;
  384. SetQuit(menu_quit,file_menu)
  385. END;
  386.  
  387. PROCEDURE TMyApplication.InitMainWindow;
  388.  
  389. BEGIN
  390. END;
  391.  
  392. PROCEDURE TInfoMenu.Work;
  393.  
  394. BEGIN
  395. IF ADialog=NIL THEN
  396. NEW(ADialog,Init(NIL,'Über KLEINES',
  397. info_dial));
  398. IF ADialog <> NIL THEN ADialog^.MakeWindow
  399. END;
  400.  
  401. PROCEDURE TOpenDialog.Work;
  402.  
  403. BEGIN
  404. IF ADialog=NIL THEN
  405. BEGIN
  406. ADialog:=NEW(PMyDialog,Init(NIL,
  407. 'KLEINES Übungsprogramm',
  408. main_dial));
  409. IF ADialog<>NIL THEN
  410. BEGIN
  411. NEW(PButton,Init(ADialog,md_ok,id_ok,
  412. TRUE,'Zeigt Eingaben in einer Alertbox
  413. an und beendet das Programm.'));
  414. NEW(PButton,Init(ADialog,md_cancel,id_cancel,
  415. TRUE,'Beendet Programm, ohne Daten
  416. Anzuzeigen.'));
  417. NEW(PEdit,Init(ADialog,md_edit,21,
  418. 'Hier kann Text eingegeben werden.'));
  419. NEW(PGroupBox,Init(ADialog,md_option_box,
  420. 'Optionen','In dieser Box befinden sich
  421. zwei RadioButtons'));
  422. NEW(PRadioButton,Init(ADialog,md_option1,TRUE,
  423. 'Die erste Option'));
  424. NEW(PRadioButton,Init(ADialog,md_option2,TRUE,
  425. 'Die zweite Option'));
  426. ADialog^.TransferBuffer:=@Buffer
  427. END
  428. END;
  429. IF ADialog<>NIL THEN ADialog^.MakeWindow
  430. END;
  431.  
  432. FUNCTION TMyDialog.OK: BOOLEAN;
  433. VAR Valid : BOOLEAN;
  434. Ausgabe: STRING;
  435.  
  436. BEGIN
  437. Valid:=INHERITED OK;
  438. IF Valid=TRUE THEN
  439. BEGIN
  440. Ausgabe:='In die Editzeile wurde "+Buffer.Kette
  441. +' eingegeben. Es wurde der Radio
  442. button ";
  443. IF Buffer.O1=bf_checked THEN Ausgabe:=Ausgabe+'1'
  444. ELSE
  445. Ausgabe:=Ausgabe+'2';
  446. Ausgabe:=Ausgabe+'. Option ausgewählt.';
  447. Application^.Alert(NIL,1,0,Ausgabe,' Ok');
  448. OK:=TRUE
  449. END
  450. ELSE
  451. OK:=FALSE
  452. END;
  453.  
  454. FUNCTION TMyDialog.Cancel: BOOLEAN;
  455.  
  456. BEGIN
  457. IF Application^.Alert(NIL,2,2,'Wirklich Beenden?',
  458. ' Abbruch| Ok')=2 THEN
  459. Cancel:=TRUE
  460. ELSE
  461. Cancel:=FALSE
  462. END;
  463.  
  464. BEGIN
  465. MyApplication.Init('KLNS','Kleines');
  466. MyApplication.Run;
  467. MyApplication.Done
  468. END.
  469.  
  470. Wir haben einen großen Teil des letzten Programmes einfach übernehmen können. 
  471. Wir haben immer noch unser Applikations-Objekt MyApplication, wir haben immer 
  472. noch das gleiche alte Dialog-Objekt TMyDialog (an OK und Cancel hat sich 
  473. eigentlich nur geändert, daß wir dort nicht mehr den Befehl zum Beenden des Programms
  474. geben).
  475. Es hat sich aber auch einiges geändert: Wir haben zwei neue Objekte 
  476. TOpenDialog und TInfoMenu (beide abgeleitet vom Typ mit den 
  477. überschriebenen Methoden und TInfoMenu.Work). In 
  478. TMyApplication.InitInstance ist einiges dazu gekommen, und dafür macht 
  479. InitMainWindow überhaupt nichts mehr.
  480.  
  481. Ehe wir unsere Menüzeile benutzen können, müssen wir natürlich erst einmal die
  482. Resource geladen haben. Wir erinnern uns, daß wir das in der Methode
  483. gemacht hatten. Direkt nach dem Laden der Resource
  484. können wir dann mit der Installation unseres Menüs loslegen:
  485.  
  486. PROCEDURE TMyApplication.InitInstance;
  487.  
  488. BEGIN
  489. LoadResource('KLEINES.RSC','');
  490. LoadMenu(main_menu);
  491. NEW(PInfoMenu,Init(@SELF,K_Ctrl,Ctrl_I,
  492. menu_info,desk_menu));
  493. NEW(POpenDialog,Init(@SELF,K_Ctrl,Ctrl_D,
  494. menu_open_dialog,file_menu));
  495. INHERITED InitInstance;
  496. SetQuit(menu_quit,file_menu)
  497. END;
  498.  
  499. Der Befehl erklärt sich ja schon fast von selbst. Das einzige, was es 
  500. dazu noch zu sagen gäbe, ist, daß LoadMenu nicht nur das Menü lädt, sondern auch 
  501. noch darstellt und mit der Verwaltung beginnt.
  502.  
  503. So wie wir schon im Dialog jedem einzelnen Button ein Objekt zugeordnet hatten, 
  504. machen wir es jetzt auch mit den einzelnen Menü-Punkten.
  505.  
  506. NEW(PInfoMenu,Init(@SELF,K_Ctrl,Ctrl_I,
  507. menu_info,desk_menu));
  508.  
  509. Das kennen wir ja schon. Wir instantiieren ein neues Objekt (diesmal vom 
  510. abgeleiteten Typ PInfoMenu von ) und initialisieren es mit dessen 
  511. Constructor Init. Dabei legen wir fest, daß das Objekt zum Menü-Eintrag 
  512. menu_info in der Spalte desk_menu gehört (ich setze bei Menü-Einträgen immer 
  513. ein vorangestelltes "menu_" und bei den Titel ein hintenangestelltes "_menu"). 
  514. Außerdem soll dieser Menü-Punkt selektiert werden, wenn gedrückt 
  515. wird.
  516. Analog läuft das dann mit dem Objekt POpenDialog.
  517.  
  518. Wenn nun ein Menü-Punkt, der zu einem entsprechenden -Objekt gehört, 
  519. selektiert wird, dann wird die Methode Work dieses Objektes gestartet. Damit 
  520. etwas passiert, wenn unsere beiden Menü-Punkte selektiert werden, müssen wir 
  521. natürlich noch die beiden Methoden und TInfoMenu.Work
  522. überschreiben.
  523.  
  524. In die Methode TOpenDialog.Work schieben wir einfach den Inhalt unseres alten 
  525. InitMainWindow, wir bauen hier also unseren Dialog auf - und diesmal macht die 
  526. Abfrage, ob der Dialog schon installiert ist, auch Sinn, denn wir können den Menü-
  527. Punkt zum Öffnen des Dialog-Fensters mehrmals aufrufen (sogar wenn der Dialog 
  528. gerade offen ist). Bei der Installation des Dialoges benutzen wir jetzt 
  529. übrigens die Variable (die zum Objekt TKeyMenu gehört). ADialog ist 
  530. ein Pointer, der auf ein Dialog-Objekt, daß zu diesem Menü-Eintrag gehört, 
  531. zeigen soll.
  532.  
  533. Wenn der oberste Menü-Punkt im Desk-Menü selektiert wird, dann soll ein 
  534. einfacher Dialog (ohne einen einzigen Button - man kann ja einfach das Fenster 
  535. zumachen, wenn man den Dialog beenden will) aufgerufen werden. Aber das ist ja 
  536. jetzt ein alter Hut, und deshalb verliere ich darüber auch kein Wort mehr.
  537.  
  538. Wir haben in diesen beiden beiden Beispiel-Programmen keine einzige Abfrage 
  539. über irgendwelche GEM-Aktionen selber machen müssen. Wir haben bisher nicht 
  540. mal eine einzige eigene Prozedur geschrieben, sondern nur bestehende Methoden 
  541. überschrieben. ObjectGEM liefert zu jedem GEM-Element einen eigenen Objekt-
  542. Typ, und zu jeder Aktion des Users gibt es eine passende Methode, die dann 
  543. aufgerufen wird. Wir brauchen uns also nur noch auf das Wesendliche zu 
  544. konzentrieren, anstatt uns mit dem Event-Loop und der Abfrage von Events 
  545. rumzuärgern.
  546.  
  547. Die ObjectGEM-Units werden wie gewohnt mit der -Klausel eingebunden. Dabei 
  548. sollte folgende Reihenfolge eigehalten werden (abgesehen von nicht benötigten 
  549. Units):
  550.  
  551. uses
  552.  
  553. Objects, OTypes, OProcs, OWindows,
  554. OValidat, ODialogs,OStdDlgs, OStdWnds, ODB;
  555.  
  556. Wenn zusätzlich noch andere Units eingebunden werden (z.B. Gem, Tos etc.), 
  557. sollten diese davor eingebunden werden, es sei denn, die Units greifen auf 
  558. Teile von ObjectGEM zurück.
  559.  
  560. Mit dem "BubbleHelp"-Hilfesystem kann sehr leicht eine kontextsensitive
  561. Hilfe realisiert werden. Dazu kann -, -
  562. und -Objekten (und davon abgeleiteten Objekten) in der
  563. jeweiligen Init-Methode ein String übergeben werden, der von der
  564. Dialogbehandlung ausgewertet wird. Im weiteren braucht dieser
  565. Hilfstext nicht weiter beachtet zu werden, einzig interessant
  566. ist noch die Methode SetHelp zum nachträglichen Ändern des
  567. Textes.
  568.  
  569. Wenn man in einem Dialog den Mauscursor auf ein solches Dialogelement
  570. bringt und die rechte Maustaste oder drückt, erscheint
  571. an der Mausposition eine Sprechblase mit dem festgelegten
  572. Hilfstext. Die Sprechblase bleibt mind. eine halbe Sekunde
  573. (ObjectGEM-intern festgelegt) sichtbar, danach kann sie mit einem
  574. Mausklick oder einem Tastendruck geschlossen werden.
  575.  
  576. Für die kontextsensitive Hilfe außerhalb von Dialogen steht die
  577. Methode zur Verfügung. Dort ist auch der
  578. Aufbau der Hilfe-Strings beschrieben.
  579.  
  580. In Zukunft wird es evtl. einen sog. "ständigen Hilfemodus" geben,
  581. bei dem eine Sprechblase erscheint, wenn sich der Mauscursor eine
  582. gewisse Zeit über einem Dialogelement befindet (wie beim Mac
  583. System 7). ObjectGEM legt dafür bereits jetzt den -Cookie
  584. an, dessen Wert sich aus der Verzögerung bis zur Aktivierung der
  585. Hilfe (unterer Integer, -1=Hilfemodus aus) und der Mindestzeit
  586. für die Sichtbarkeit der Sprechblase (oberes Word) zusammensetzt.
  587.  
  588. Die Objekte , und besitzen das Feld
  589. Clipboard, das auf ein -Objekt zeigt. Normalerweise gibt
  590. es nur ein globales Clipboard-Objekt, falls aber eine Spezialisierung
  591. notwendig sein sollte, steht die Methode GetClipboard zur Verfügung.
  592.  
  593. Um auf das Clipboard zugreifen zu können (lesend oder schreibend),
  594. muß man es mit OpenClipboard öffnen. Von GetClipboardFilename
  595. erhält man eine komplette Pfadangabe incl. Dateinamen für das Klemmbrett -
  596. nur die Extension fehlt noch (z.B. C:CLIPBRDSCRAP.).
  597. Mit IsClipboardFormatAvailable und GetPriorityClipboardFormat
  598. kann man komfortabel nach bestimmten Dateitypen im Klemmbrett
  599. suchen, ansonsten kann man nun mit den "normalen" Dateifunktionen
  600. auf das Klemmbrett zugreifen. Abschließend muß man das Klemmbrett
  601. mit CloseClipboard wieder schließen und damit freigeben.
  602.  
  603. Hat man den Inhalt des Klemmbretts verändert, sollte man vorher
  604. noch SetClipboardFormat aufrufen, damit die beim Schließen
  605. verschickte SC_CHANGED-Message korrekt gesetzt werden kann.
  606.  
  607. Wichtig: Es kann immer nur ein TClipboard-Objekt Zugriff auf
  608. das Klemmbrett haben. Wenn also ein Zugriff immer bereits beim
  609. Öffnen scheitert, kann es sein, daß bei einem anderen Clipboard-
  610. Objekt das Schließen vergessen wurde.
  611.  
  612. In ObjectGEM ist das Drag&Drop-Protokoll in der Version 1.1 implementiert.
  613. Der Drag&Drop-Mechanismus steht nur unter MultiTOS zur Verfügung.
  614.  
  615. Wenn ein Programm Drag&Drop unterstützen soll, müssen zumindest
  616. die Methoden DDHeaderReply und DDReadData (bzw. DDReadArgs)
  617. überschrieben werden. Das Einlesen der Daten muß in letztgenannter
  618. Methode selbst vorgenommen werden. Da während des Drag&Drop-
  619. Protokolls der Bildschirm nicht blockiert werden darf, erhält
  620. man nach erfolgreicher Kommunikation in der Methode DDFinished
  621. die Möglichkeit, die Daten entsprechend auszuwerten.
  622.  
  623. Wenn der Aufbau der Kommunikation nicht unnötig in die Länge
  624. gezogen werden soll, muß dafür die Methode DDGetPreferredTypes
  625. überschrieben werden, in der man die möglichen Dateitypen einschränken kann.
  626.  
  627. Soll das Programm auch auf den PATH-Parameter positiv antworten,
  628. muß DDGetPath effektiv gemacht werden.
  629.  
  630. ObjectGEM stellt eine erweiterte Dialogbehandlung zur Verfügung.
  631. Folgende Eigenschaften sind zusätzlich zu den üblichen GEM-Möglichkeiten
  632. vorhanden:
  633.  
  634.  
  635. Der Edit-Cursor kann mit der Maus verschoben werden
  636. Folgende Tastenkombinationen stehen in einem Edit-Feld zur Verfügung:
  637.  
  638.  
  639.  
  640. geht zum vorherigen Eingabefeld
  641.  
  642.  
  643.  
  644. geht zum nächsten Eingabefeld
  645.  
  646.  
  647.  
  648. Cursor innerhalb des Feldes bewegen
  649.  
  650. Cursor an Feldanfang
  651.  
  652. Cursor an Feldende
  653.  
  654.  
  655.  
  656. Cursor auf erstes Eingabefeld
  657.  
  658.  
  659.  
  660. Cursor auf letztes Eingabefeld
  661.  
  662. Zeichen links vom Cursor löschen
  663.  
  664. Zeichen rechts vom Cursor löschen
  665.  
  666. Feld löschen
  667.  
  668. s.u.
  669.  
  670.  
  671. Jedes Eingabefeld, dem ein -Objekt zugeordnet ist, merkt
  672. sich die Position des Edit-Cursors bis zur nächsten Aktivierung.
  673. Außerdem kann mit die letzte Änderung rückgängig
  674. gemacht werden.
  675. Dialogelemente, bei denen ein Buchstabe unterstrichen angezeigt
  676. wird, können mit aktiviert werden.
  677. -Objekte, bei denen cs_WorkBackground gesetzt ist (das
  678. ist die Standard-Einstellung), können auch im Hintergrund
  679. bedient werden. Um ein solches Dialogfenster wieder in den
  680. Vordergrund zu holen, muß man einen Doppelklick rechts auf
  681. den Arbeitsbereich des Fensters ausführen.
  682. Modale Dialogekönnen durch Anklicken eines inaktiven Dialogelements
  683. (z.B. Text oder der Hintergrund) bei gedrückter
  684. linker Maustaste verschoben werden.
  685. Bei einem Klick außerhalb eines modalen Dialogs wird dieser um
  686. den Mauszeiger zentriert.
  687. Befindet sich der Mauscursor über einem Dialogelement, dem ein
  688. TControl-Objekt zugeordnet ist (das sollte bei den meisten der
  689. Fall sein), kann mit der rechten Maustaste oder mit die
  690. sog. aufgerufen werden.
  691.  
  692. Mit cs_WorkBackground können Fenster dazu gebracht werden, daß
  693. man sie im Hintergrund bedienen kann (unter allen TOS-Versionen).
  694. Dies gilt natürlich nur für den Arbeitsbereich, die
  695. Fensterkomponenten können nur im Hintergrund angewählt werden,
  696. wenn das Betriebssystem dies unterstützt (z.B. MultiTOS, WINX).
  697. Solche Fenster können nur noch durch Anklicken einer Fenster-Komponente
  698. (Titelzeile etc.) getoppt werden, oder - dies ist
  699. ein ObjectGEM-spezifisches Feature - mit einem Doppelklick rechts
  700. im Arbeitsbereich!
  701.  
  702. In den TWindow-Fensterobjekten sind z.Z. folgende Tastatur-Shortcuts
  703. vorgesehen (#bedeutet, daß die Taste im Ziffernblock
  704. gemeint ist):
  705.  
  706.  
  707. Wählt alle passenden Elemente im Fenster aus
  708.  
  709. (siehe )
  710.  
  711. Führt die "Kopieren"-Operation durch
  712.  
  713. (siehe )
  714.  
  715. Druckt den Fensterinhalt aus
  716.  
  717. (siehe bzw. TTextWindow.Print)
  718.  
  719. Schließt das Fenster
  720.  
  721. Führt die "Einfügen"-Operation durch
  722.  
  723. (siehe )
  724.  
  725. Wechselt die Fenster der Applikation zyklisch
  726.  
  727. (mit in umgekehrter Reihenfolge)
  728.  
  729. Führt die "Ausschneiden"-Operation durch
  730.  
  731. (siehe )
  732.  
  733. # Bringt das Fenster auf Maximalgröße
  734.  
  735. # Bringt das Fenster in den Hintergrund (AES 4.0)
  736.  
  737. # Ikonifiziert das Fenster (nur mit ICFS)
  738.  
  739. Führt die "Entfernen"-Operation durch
  740.  
  741. (siehe )
  742.  
  743. Verläßt das Programm
  744.  
  745. (dies ist eigentlich kein Fenster-Shortcut)
  746.  
  747.  
  748. Ab AES 4.10 unterstützt ObjectGEM Iconification, d.h. GetStyle
  749. liefert zusätzlich den Wert SMALLER zurück, und im Fenster erscheint
  750. links neben dem Fuller noch der "Verkleinerungsknopf".
  751.  
  752. Wenn dieser Button angewählt wird, wird das entsprechende Fenster
  753. ikonifiziert. Dem Icon-Fenster kann per GetIconTitle ein neuer
  754. Titel zugewiesen werden, außerdem wird bei einem Redraw nun die
  755. Methode IconPaint aufgerufen. Der Status eines Fensters läßt sich
  756. mit IsIconified abfragen.
  757.  
  758. Wenn beim Anklicken des SMALLERs zusätzlich 
  759. gedrückt wird, wird die gesamte Applikation ikonifiziert, d.h. alle
  760. Fenster werden in einem Icon-Fenster zusammengefaßt. Dafür
  761. stehen ähnliche Funktionen wie bei einem Fenster zur Verfügung.
  762. Wichtig: Hierbei werden die Fenster der Applikation nicht
  763. geschlossen, sondern nur rechts so weit über den Bildschirmrand
  764. geschoben, daß man sie nicht mehr sieht und der Benutzer keine
  765. Aktionen mehr an ihnen durchführen kann. Für die Applikation
  766. wird dann ein neues Icon-Fenster geöffnet.
  767.  
  768. Soll in einem ikonifizierten Fenster automatisch ein Icon angezeigt
  769. werden, muß aufgerufen werden. Damit auch
  770. bei einem Applikations-Icon-Fenster ein Icon erscheint, steht die
  771. Methode zur Verfügung. Dialoge übernehmen
  772. dieses Icon automatisch, wenn ihnen kein eigenes Icon zugewiesen
  773. wird.
  774.  
  775. Ist ein ICFS-Server installiert, so ist Iconification auch unter
  776. alten TOS-Versionen möglich. Wird beim Anklicken der CLOSERs
  777. gedrückt, wird das Fenster ikonifiziert. Das
  778. Verkleinern aller Fenster mit ist aus technischen
  779. Gründen (noch) nicht möglich bzw. sinnvoll. In einer späteren
  780. Version wird es allerdings auch die ICFS-Iconification mit
  781. geben (alle Fenster werden einzeln verkleinert).
  782. ObjectGEM liegt der ICFS-Server von Dirk Haun und das ICFS-CPX
  783. von John McLoud bei.
  784.  
  785. Ikonifizierte Fenster oder Applikationen erhalten von ObjectGEM
  786. nur noch Timer- sowie ausgesuchte Message-Events. Evtl. kann in
  787. Zukunft aber ein Flag gesetzt werden, so daß auch in einem Icon-Fenster
  788. Aktionen durchgeführt werden können.
  789.  
  790. In den -Menüs ist folgende Tastatursteuerung vorgesehen:
  791.  
  792.  
  793. Wählt den markierten Eintrag aus
  794.  
  795.  
  796.  
  797.  
  798. Bricht das Popup-Menü ab
  799.  
  800.  
  801.  
  802. Bringt die Markierung auf den ersten Eintrag
  803.  
  804.  
  805.  
  806. Bringt die Markierung auf den letzten Eintrag
  807.  
  808.  
  809.  
  810. Bewegt die Markierung nach oben
  811.  
  812. Bewegt die Markierung nach unten
  813.  
  814.  
  815. Mit den ObjectGEM-Profile-Routinen können die bei vielen Applikationen
  816. vorhandenen INF-Dateien sehr leicht realisiert werden.
  817. Sie haben außerdem den Vorteil, daß sie als ASCII-Texte
  818. verwaltet werden, so daß sie - wenn nötig - auch "von Hand"
  819. verändert werden können.
  820.  
  821. Außerdem werden - wenn die Environmentvariable HOME und das Flag
  822. as_UseHomeDir gesetzt ist - diese Konfigurationsdateien an einem
  823. zentralen Ort (eben dem User-Home-Verzeichnis) gespeichert, so
  824. daß auch eine Multi-User-Umgebung realisierbar ist. Wenn 
  825. nicht gesetzt ist, werden die Dateien wie gewohnt im Ordner der
  826. Applikation angelegt.
  827.  
  828. Ein Profile setzt sich aus Blöcken zusammen. Jeder Block hat eine
  829. "Überschrift" (in eckigen Klammern, bei den Profile-Routinen auch
  830. mit "Anwendungsname" bezeichnet). Nach diese Überschrift folgen
  831. die Schlüsselnamen mit den zugehörigen Werten, Leerzeilen sind
  832. nur zum Trennen der Blöcke erlaubt. Kommentare beginnen mit einem
  833. Semikolon oder # am Zeilenanfang, Kommentarblöcke werden mit ## eingeschlossen.
  834. Ein Eintrag innerhalb eines Profiles
  835. muß durch den Anwendungs- und Schlüsselnamen eindeutig bestimmt
  836. sein, ansonsten wird nur das erste Vorkommen beachtet.
  837. Ein Profile könnte also z.B. so aussehen:
  838.  
  839.  
  840. ; Das ist ein Kommentar innerhalb eines Profiles
  841. # das auch
  842. [Block 1]
  843. Var_1=Test-Text
  844. Var_2=42
  845.  
  846. ## hier beginnt ein Kommentarblock
  847. und in der nächsten Zeile hört er auf
  848. ##
  849. [nächster Block]
  850. Var_2=die hat nichts mit o.g. Variable zu tun
  851. Var_3=2147483647
  852. Hallo.Welt=Das ist ein Test!
  853.  
  854. Zum Auswerten eines Profiles stehen Routinen für ganze Zahlen
  855. (GetPrivateProfileInt, WritePrivateProfileInt) und für
  856. Zeichenketten (GetPrivateProfileString, WritePrivateProfileString) zur
  857. Verfügung. Sollen Fließkommazahlen bearbeitet werden, muß man
  858. diese in Zeichenketten umwandeln (z.B. mit ftoa, atof).
  859.  
  860. Profiles, die direkt auf einer Datei arbeiten, sind recht langsam,
  861. vor allem beim Schreiben. Deshalb besteht die Möglichkeit,
  862. ein Profile mit OpenPrivateProfile in den Speicher zu laden, wo
  863. die Bearbeitung deutlich schneller ist. Da immer nur ein Profile
  864. im Speicher verwaltet werden kann, werden Zugriffe auf andere
  865. Profiles weiterhin direkt auf der Platte (bzw. Diskette) durchgeführt.
  866. ClosePrivateProfile braucht nicht explizit aufgerufen
  867. zu werden, dies geschieht automatisch beim Programmende. Man
  868. sollte allerdings nach dem Schreiben von Daten immer die Routine
  869. SavePrivateProfile aufrufen, da man z.B. bei Accessories nicht
  870. davon ausgehen kann, daß die Applikation verlassen werden kann.
  871.  
  872. Die oben erwähnten Routinen bearbeiten private Profiles, d.h.
  873. Applikations-spezifische Konfigurationsdateien. Da es aber auch
  874. wünschenswert sein kann, bestimmte Werte systemglobal festzulegen,
  875. ist z.Z. eine Datei in der Diskussion, die von
  876. allen Applikationen verwendet werden kann. Für diese Datei stehen
  877. spezielle Routinen zur Verfügung (GetProfileString etc.). Da
  878. die Standardisierung aber noch nicht abgeschlossen ist, kann sich
  879. am Namen, Ort, Inhalt etc. der Datei noch etwas ändern.
  880.  
  881. Folgendes sollte bei der Resource-Erstellung für ObjectGEM
  882. beachtet werden:
  883.  
  884.  
  885. Das höherwertige Byte von ob_type (AESOBJECT) darf unter
  886. ObjectGEM weder verwendet noch verändert werden! Abgesehen
  887. davon, daß es eine Zeit lang unter MultiTOS Probleme mit
  888. solchen Programmen gegeben hat, benötigt ObjectGEM dieses
  889. Byte für interne Zwecke. Durch den objektorientierten Ansatz
  890. und die TControl-Schnittstellenobjekte sollte die Verwendung
  891. dieses Bytes allerdings auch nicht nötig sein.
  892. Alle mit ObjectGEM verwendeten Resourcen sollten wie folgt
  893. sortiert sein (eine entsprechende Option sollte in jedem RCS
  894. zu finden sein):
  895.  
  896.  
  897. 1 2 3
  898. 4 5 6
  899.  
  900. Die korrekte Größe für Dialogelemente, denen später ein
  901. TCheckBox-, TRadioButton- oder TTriState-Objekt zugeordnet
  902. werden soll, kann wie folgt bestimmt werden: Man nimmt im RCS
  903. ein BUTTON-Element und verändert den Text wie gewünscht. An
  904. den Text werden allerdings noch drei (bzw. zwei, wenn eine
  905. Shortcut-Markierung verwendet wird) Leerzeichen angehängt.
  906. Nun wird das BUTTON-Element vom RCS entsprechend lang gezeichnet.
  907. Zum Schluß löscht man die Leerzeichen wieder, verändert
  908. die Größe des BUTTON-Elements allerdings nicht mehr.
  909. Im ObjectGEM-Programm werden die neuen Buttons nun korrekt
  910. gezeichnet.
  911. Bei den Objekten TCheckBox/TTriState wird der selektierte Zustand
  912. normalerweise als Häkchen dargestellt. Wenn in der Resource
  913. allerdings das Flag CROSSED gesetzt ist, werden daraus
  914. "Ankreuzkästchen".
  915. Toolbar-Elemente werden unter neueren TOS-Versionen automatisch
  916. mit 3D-Effekten versehen, wenn sie vom Typ G_BOX, G_BOXTEXT,
  917. G_BUTTON, G_BOXCHAR oder G_FBOXTEXT sind. Elemente vom Typ
  918. G_BOXTEXT oder G_FBOXTEXT sollten mit dem kleinen Zeichensatz
  919. sowie den Stati SHADOWED und OUTLINED versehen werden; dadurch
  920. haben sie einen Pseudo-3D-Effekt, der ab AES 3.40 automatisch
  921. durch den "echten" Effekt ausgetauscht wird.
  922. Wenn ein Toolbar-Button nicht mit einem TToolbar-Objekt
  923. verknüpft wird (siehe "Toolbars"), muß in ob_state SELECTABLE
  924. gesetzt sein.
  925. Wenn bei InitResource/LoadResource zwei RSC-Dateien für die
  926. unterschiedlichen Auflösungen verwendet werden, muß man daran
  927. denken, daß die Indizes der Objekte in beiden Dateien gleich
  928. sein müssen, da nur eine Include-Datei verwendet werden
  929. kann.
  930. ObjectGEM kommt auch mit RSC-Dateien zurecht, in denen das
  931. pe_tvalid-Feld verkürzt ist. Die nötigen Zeichen der Maske
  932. werden ergänzt.
  933. In stehen folgende Zeichen zusätzlich zur Verfügung:
  934.  
  935. "H" für Hexadezimalzahlen: "0".."9", "a".."f", "A".."F"
  936. "D" für Dezimalzahlen: "0".."9", "+", "-", ",", "."
  937. "+" für Vorzeichen: "+", "-"
  938.  
  939. Fenster-Toolbars bestehen aus ganz normalen Dialog-Bäumen in der
  940. Resource-Datei, die in SetupWindow mittels LoadToolbar mit dem
  941. Fenster verknüpft werden. Um eine einfach Bearbeitung zu gewährleisten,
  942. sollten danach alle Toolbar-Buttons mit -Objekten verknüpft
  943. werden, die als Schnittstellenobjekte dienen.
  944.  
  945. Eine andere Möglichkeit sind Anwender-konfigurierbare Toolbars.
  946. Dabei kann der spätere Anwender des Programms sich seine Toolbar-Buttons
  947. mit einem Resource Construction Set zusammenstellen.
  948. Diese Buttons werden nicht mit TToolbar-Objekten verknüpft
  949. (der Programmierer kann ja nicht alle Anwenderwünsche berücksichtigen),
  950. sondern über den erweiterten Objekttyp mit einem
  951. Menüeintrag in der Menüleiste der Applikation. Dieses ist die
  952. einzige Situation, in der die Verwendung des höherwertigen
  953. Bytes von ob_type unter ObjectGEM gestattet ist!!!
  954.  
  955. Findet der Toolbar-Dispatcher im höherwertigen Byte eine Null
  956. vor (das sollte bis jetzt immer der Fall sein), passiert gar
  957. nichts. Ist dort allerdings ein Wert ungleich Null eingetragen,
  958. wird MNSelected mit eben diesem Wert als Index des gewählten
  959. Menüeintrags aufgerufen.
  960.  
  961. Wichtig: Dieser Mechanismus funktioniert auch, wenn TToolbar-Objekte
  962. eingesetzt werden, d.h. der Programmierer kann diesen
  963. Effekt bewußt ausnutzen. Der Aufruf erfolgt in diesem Fall
  964. nach dem Aufruf der Work-Methode.
  965.  
  966. Wenn Anwender-konfigurierbare Toolbars eingesetzt werden, muß
  967. der Programmierer dafür sorgen, daß die Indizes der Menüeinträge
  968. dokumentiert werden. Außerdem wäre es nett, wenn dem Anwender
  969. dann z.B. Mini-Icons für die wichtigsten Funktionen zur Verfügung
  970. gestellt würden.
  971.  
  972. ObjectGEM verwendet das XAcc-Protokoll nach der Definition vom
  973. 28.11.1992, d.h. auch unter MultiTOS ist die korrekte Protokoll-Behandlung
  974. gesichert.
  975.  
  976. Als Programmierer braucht man sich nicht um die Einzelheiten
  977. des Protokolls kümmern, sondern man kann direkt das Ergebnis
  978. in der XAccList (z.B. per TApplication.FindApplication)
  979. auswerten. Die einzig interessante "Verwaltungs"-Routine dürfte
  980. TApplication.XAccInsert sein.
  981.  
  982. Die XAcc-Eigenschaften des ObjectGEM-Programms werden in der
  983. Methode TApplication.GetXAccAttr festgelegt. Wenn man also
  984. besondere Eigenschaften kennzeichnen möchte, muß man diese
  985. Methode überschreiben. Man kann dort auch die "Extended names"
  986. festlegen, die dann von ObjectGEM automatisch korrekt verschickt
  987. werden.
  988.  
  989. Wichtige Methoden für das XAcc-Protokoll sind diejenigen, mit
  990. denen ein Datenaustausch durchgeführt werden kann. Dies sind
  991. die TApplication-Methoden XAccText, XAccKey, XAccMeta und
  992. XAccIMG. Diese Methoden dienen zum Empfangen von Daten; ein
  993. Verschicken wird z.Z. von ObjectGEM noch nicht direkt unterstützt.
  994.  
  995. ObjectGEM wertet außerdem das AV-Protokoll aus. Dies geschieht
  996. ebenfalls automatisch, und es werden die gleichen Datenstrukturen
  997. verwendet. Wie beim XAcc-Protokoll dürfte auch nur die Methode
  998. TApplication.AVInsert interessant sein, alle spezifischen AV-Messages
  999. werden weiterhin an TApplication.HandleAV weitergeleitet.
  1000. Ist ein AV-Server vorhanden, befindet sich seine AES-ID
  1001. im Feld TApplication.AVServer.
  1002.  
  1003. In den Dialogen sollte so oft wie möglich die "BubbleHelp" unterstützt werden 
  1004. (siehe TControl). Ein Hilfesystem bringt nur dann etwas, wenn es konsequent 
  1005. eingesetzt wird.
  1006.  
  1007. ObjectGEM unterstützt neue, zu BP 7.0 kompatible Runtime-Errors:
  1008.  
  1009.  
  1010. Fehler-Nr. Bedeutung
  1011.  
  1012.         211 Aufruf einer abstrakten Methode
  1013.  
  1014.         ("Call to abstract method")
  1015.  
  1016.         Dieser Fehler wird normalerweise von der Prozedur
  1017.  
  1018.         Abstract ausgelöst und zeigt an, daß Sie einen
  1019.  
  1020.         abstrakten Objekttyp nicht abgeleitet und die
  1021.  
  1022.         entsprechenden Methoden überschrieben haben;
  1023.  
  1024.         TSortedCollection ist ein Beispiel dafür
  1025.  
  1026.         213 Kollektion-Index außerhalb des gültigen Bereichs
  1027.  
  1028.         ("Index range error")
  1029.  
  1030.         Einer TCollection-Methode wurde ein ungültiger
  1031.  
  1032.         Index übergeben (d.h. zu klein/groß).
  1033.  
  1034.         214 Kollektion-Überlauf
  1035.  
  1036.         ("Collection overflow")
  1037.  
  1038.         Die Kollektion kann kein neues Element mehr
  1039.  
  1040.         aufnehmen, d.h. der Speicher ist voll.
  1041.  
  1042.  
  1043. Für viele Fenster-Routinen etc. stellt ObjectGEM "neue" Methoden zur Verfügung, 
  1044. die statt der alten verwendet werden sollten (bzw. müssen); z.B. muß statt
  1045. wind_calc nun die TWindow-Methode WindCalc aufgerufen werden.
  1046. Dadurch ist es sauber geschriebenen Programmen dann egal, ob z.B. noch eine
  1047. Toolbar oder eine Menüleiste im Fenster installiert wird, da ObjectGEM nun für
  1048. die Verwaltung des Work-Bereichs etc. zuständig ist.
  1049.  
  1050. alte Funktion                                        "neue" Methode
  1051.  
  1052.     evnt_timer(1,0) appl_yield
  1053. hline
  1054.     form_alert                                            TApplication.Alert
  1055.  
  1056.     form_dial(FMD_FINISH)        TWindow.ForceRedraw
  1057.  
  1058.     Neuzeichnen des Fensters            TWindow.WMRedraw
  1059.  
  1060.                                                                         TApplication.InvalidateRect
  1061.  
  1062.         Neuzeichnen des Desktops                TApplication.DeskRedraw
  1063.  
  1064.     form_do                                                    TApplication.ExecDialog
  1065.  
  1066.                                                                         (besser TDialog verwenden!)
  1067.  
  1068.         Popup-Menüs                                            TApplication.Popup
  1069.  
  1070. fsel_input                                    FileSelect
  1071.  
  1072. fsel_exinput 
  1073.  
  1074. GetFreeString                                        TApplication.GetFString
  1075.  
  1076. graf_mouse(ARROW) ArrowMouse
  1077.  
  1078. graf_mouse(BUSYBEE) BusyMouse
  1079.  
  1080. graf_mouse(M_OFF) HideMouse
  1081.  
  1082. graf_mouse(M_ON) ShowMouse
  1083.  
  1084.     menu_bar                                                TApplication.LoadMenu
  1085.  
  1086.                                                                         TApplication.DrawMenu
  1087.  
  1088.                                                                         TApplication.FreeMenu
  1089.  
  1090.     objc_change                                SetState, GetState,
  1091.  
  1092.         Ändern des Objektstatus                Enable, Disable,
  1093.  
  1094.                                                                     SetText, GetText,
  1095.  
  1096.                                                                     SetCheck, GetCheck,
  1097.  
  1098.                                                                     Check, Uncheck,
  1099.  
  1100.                                                                     Toggle, Gray
  1101.  
  1102.     rsrc_free                                                TApplication.FreeResource
  1103.  
  1104.     rsrc_gaddr                                            TApplication.GetAddr
  1105.  
  1106.                                                                         TApplication.GetFImagePtr
  1107.  
  1108.                                                                         TApplication.GetFStringPtr
  1109.  
  1110.     rsrc_load                                                TApplication.LoadResource
  1111.  
  1112.                                                                         TApplication.InitResource
  1113.  
  1114.     wind_calc                                                TWindow.WindCalc
  1115.  
  1116.     wind_close                                            TWindow.CloseWindow
  1117.  
  1118.     wind_create                                            TWindow.Create
  1119.  
  1120.     wind_delete                                            TWindow.Destroy
  1121.  
  1122.  
  1123. alte Funktion                                        "neue" Methode
  1124.  
  1125.     wind_get(WF_CURRXYWH)            TWindow.GetCurr
  1126.  
  1127.     wind_get(WF_FULLXYWH)            TWindow.GetFull
  1128.  
  1129.     wind_get(WF_WORKXYWH)            TWindow.GetWork
  1130.  
  1131.     wind_get(DESK,WF_WORKXYWH) GetDesk
  1132.  
  1133.     wind_open                                                TWindow.OpenWindow
  1134.  
  1135.     wind_set(WF_CURRXYWH)            TWindow.SetCurr
  1136.  
  1137.                                                                         TWindow.SetWork
  1138.  
  1139.                                                                         TWindow.FullSize
  1140.  
  1141.     wind_set(WF_INFO)            TWindow.SetSubTitle
  1142.  
  1143.         WindSetInfo 
  1144.  
  1145.     wind_set(WF_NAME)            TWindow.SetTitle
  1146.  
  1147.         WindSetTitle 
  1148.  
  1149.     wind_set(DESK,WF_NEWDESK)                TApplication.InstallDesktop
  1150.  
  1151.                                                                         TApplication.RemoveDesktop
  1152.  
  1153.     wind_set(WF_TOP)                        TWindow.Top
  1154.  
  1155. Programm verlassen                            TApplication.Quit
  1156.  
  1157.                                                                         (geschieht, wenn nicht anders
  1158.  
  1159.                                                                         angegeben, beim Schließen eines
  1160.  
  1161.                                                                         Fensters automatisch, siehe
  1162.  
  1163.                                                                         Beispielprogramme)
  1164.  
  1165.  
  1166. [15mm]
  1167.  
  1168. Im globalen Record stehen die aktuellen, für ObjectGEM gültigen VDI-Attribute,
  1169. die auch von Programmen genutzt werden können. Es ist allerdings 
  1170. nicht sicher, daß dieser Record "bis in alle Ewigkeit" unterstützt wird. Es 
  1171. existiert deshalb zwar die Routine ; Programme sollten nach 
  1172. Möglichkeit aber den Zugriff auf GP vermeiden (im Gegensatz zum bisher 
  1173. Dokumentierten)!!!
  1174.  
  1175. Die Unit installiert eine neue -Funktion,
  1176. die bei Fehlschlagen einer Speicheranforderung einen nil-Pointer zurückgibt.
  1177. wird von OWindows umgelenkt, so daß bei einem
  1178. außerordentlichen Programmabbruch noch versucht werden kann, ein
  1179. evtl. angelegtes Applikations-Objekt freizugegeben.
  1180. Wenn SpeedoGDOS installiert ist, werden die Speedo-Fehlermeldungen
  1181. mittels vst_error so umgeleitet, daß diese nicht mehr
  1182. auf dem Bildschirm angezeigt werden, sondern mit ChkSpeedoError
  1183. abgefragt werden können.
  1184. Ist MiNT oder MultiTOS aktiv, lenkt TApplication.InitGEM die
  1185. Signale SIGTERM und SIGQUIT auf einen eigenen Handler um, damit
  1186. die Applikation korrekt verlassen werden kann.
  1187. Wenn appl_getinfo vorhanden ist, wird diese Auskunftsfunktion
  1188. verwendet, um spezielle Systemeigenschaften zu ermitteln (so
  1189. wird die Mag!C-Anpassung realisiert). Für das Vorhandensein der
  1190. Routine werden AES- bzw. Mag!C-Version getestet sowie die ?AGI-
  1191. Methode unterstützt (appl_find('?AGI')=0).
  1192. Ist MultiTOS vorhanden, wird zur Clipboard-Blockierung das AES-interne
  1193. -Semaphor verwendet.
  1194. Wenn Let'em Fly installiert ist, wird die Dialog-Flugroutine
  1195. sowie die Routine beim Klick außerhalb des Dialogs für modale
  1196. Dialoge verwendet.
  1197. Der -Cookie (Virtual Screen) wird beachtet.
  1198. WINX ab Version 2.2 wird direkt unterstützt, z.B. durch die
  1199. WMArrowed-Methode (Scrollboxen).
  1200.  
  1201. Die GEM-Message GO_PRIVATE ($1235) wird intern mit folgenden
  1202. Sub-Opcodes in msg[3] verwendet:
  1203.  
  1204.  
  1205. GOP_GETVERSION 0 dient als Aufforderung, eine
  1206.  
  1207. GOP_VERSION-Message zu schicken
  1208.  
  1209. GOP_TOOLBAR 1 siehe TToolbar.TestMessage
  1210.  
  1211. GOP_SETQUIT 2 wird von LoadMenu verschickt, um den
  1212.  
  1213. Menüeintrag (msg[4]) und -titel (msg[5])
  1214.  
  1215. für das -Objekt zu setzen;
  1216.  
  1217. beim Empfang dieser Message ruft
  1218.  
  1219. MUMesag die Methode SetQuit auf
  1220.  
  1221. GOP_VERSION $7fff wird als Antwort auf GOP_GETVERSION
  1222.  
  1223. verschickt; in msg[4] erhält man die
  1224.  
  1225. jeweilige GOVersion
  1226.  
  1227.  
  1228. ObjectGEM setzt die Ideen von ObjectWindows für BorlandPascal unter Windows
  1229. für das Atari-GEM um. Abgesehen von offensichtlichen Unterschieden
  1230. (z.B. beim Event-Handling) gibt es aber auch noch andere, die hier
  1231. besprochen werden sollen.
  1232.  
  1233. In ObjectGEM sind die meisten Methoden virtuell, wodurch es besser möglich sein 
  1234. sollte, in den Programmablauf - wenn nötig - einzugreifen.
  1235.  
  1236. Außerdem wird in ObjectGEM recht wenig vom Typ PChar Gebrauch gemacht. Dies 
  1237. dient zum einen zur einfacheren Programmierung (normale Strings reichen 
  1238. meistens aus), zum anderen gab (und gibt) es offensichtlich Probleme mit den 
  1239. nullterminierten Strings und der zugehörigen Unit.
  1240.  
  1241. Im folgenden sind Routinen aufgelistet, die zwar nicht 100% kompatibel, aber 
  1242. zumindest recht ähnlich sind:
  1243.  
  1244.  
  1245. ObjectWindows/Windows ObjectGEM
  1246.  
  1247.  
  1248. BringWindowToTop TWindow.Top
  1249.  
  1250.     CheckDlgButton SetCheck
  1251.  
  1252.     GetActiveWindow TApplication.GetPTopWindow
  1253.  
  1254.     GetClientRect TWindow.GetWork
  1255.  
  1256.     GetDesktopWindow DESK
  1257.  
  1258.     GetVersion GEMVersion
  1259.  
  1260. MiNTVersion
  1261.  
  1262. TOSVersion
  1263.  
  1264. GetWindowRect TWindow.GetCurr
  1265.  
  1266. IntersectRect rc_intersect
  1267.  
  1268. MapVirtualKey MapKey
  1269.  
  1270. MessageBox TApplication.Alert
  1271.  
  1272. PostQuitMessage TApplication.Quit
  1273.  
  1274. Yield appl_yield
  1275.  
  1276.  
  1277. "Objektorientierte Programmierung: Philosophie des Programmierens, die von einer
  1278. Welt ausgeht, die aus gleichberechtigten und einheitlich erscheinenden Objekten
  1279. besteht..." Das sagt zumindest der Duden "Informatik". Und wer das jetzt sofort
  1280. und uneingeschränkt verstanden hat, sollte gar nicht mehr weiterlesen, denn er
  1281. (oder sie) wird am folgenden keinen Spaß, geschweige denn irgend eine wichtige
  1282. Information finden.
  1283.  
  1284. Was nun aber ist OOP wirklich? Normalerweise wird OOP nicht konkret definiert,
  1285. sondern vielmehr durch Beispiele erklärt und mit Metaphern umschrieben. Und so
  1286. wollen auch wir uns diesem mysteriösen Begriff ein wenig nähern.
  1287.  
  1288. Normalerweise fangen alle Erklärungsversuche jetzt an, eine Objekthierarchie
  1289. von Grafikelementen aufzustellen (Werte, Punkte, Linien...). Es gibt aber auch
  1290. einen interessanteren Ansatz. Wieviele verschiedene Obstsorten haben Sie gerade
  1291. bei sich in der Küche? Sicherlich eine ganze Menge. Und all diese Sorten lassen
  1292. sich schön übersichtlich in verschiedene Klassen einteilen (Südfrüchte,
  1293. Beerenfrüchte, Kernobst, bestrahltes Obst, gespritztes Obst...). Man kann aber
  1294. auch etwas ganz anderes damit machen.
  1295.  
  1296. Für 6 Personen
  1297.  
  1298. 750g gemischtes Obst (Birnen, Nektarinen,
  1299.  
  1300. Aprikosen, Erd- und Johannisbeeren)
  1301.  
  1302. 2EL Ahornsirup
  1303.  
  1304. 2cl Aprikosenlikör
  1305.  
  1306. 1 Vanilleschote
  1307.  
  1308. 50g weiche Butter
  1309.  
  1310. 50g Puderzucker
  1311.  
  1312. 1 Ei, Salz
  1313.  
  1314. 100g Mehl
  1315.  
  1316. 1-2EL Milch
  1317.  
  1318. 2 Eigelb
  1319.  
  1320. 1/8l Marsalawein
  1321.  
  1322. 1EL Zitronensaft
  1323.  
  1324.  
  1325. [2mm]
  1326.  
  1327. Das Obst waschen, abtrocknen, zerkleinern und mit Sirup sowie Likör mischen.
  1328. Das Vanillemark aus der Schote schaben und mit Butter, Puderzucker, Ei,
  1329. 1 Prise Salz, Mehl und Milch zum dünnflüssigen Teig verrühren. Diesen
  1330. sofort zu 6 Plätzchen ( 12cm) auf Backpapier streichen und im
  1331. 200 Grad (Gas: Stufe 3) heißen Ofen in 12-15 Minuten goldgelb werden
  1332. lassen. Noch heiß über umgestülpten Gläsern rund formen. Eigelb mit
  1333. Marsala und dem Zitronensaft im heißen Wasserbad schaumig schlagen.
  1334. Den Obstsalat in die kalten, zu Schälchen geformten Plätzchen füllen und mit der
  1335. Weinschaumsauce überziehen. Fertig!
  1336.  
  1337. Sei nun die Folge der Kalorien.
  1338. Diese kann dann wesentlich einfacher mit 
  1339. berechnet werden.
  1340.  
  1341. Nun ja, zugegeben, soooo viel haben wir über OOP in diesem Kapitel nicht erfahren,
  1342. aber der Obstsalat schmeckt wirklich gut!
  1343.  
  1344. meyer Bertrand Meyer, Objektorientierte Softwareentwicklung,
  1345. Hanser, Wien; Prentice Hall, London (1990)
  1346. profi Jankowski, Rabich, Reschke, Atari Profibuch, 10. Auflage, 
  1347. SYBEX, D"usseldorf (1992)
  1348.  
  1349. compendium Scott Sanders, The ATARI Compendium,
  1350. SDS Publishing (1993)
  1351. geiss Dieter Geiß, Jürgen Geiß, Vom Anfänger zum GEM-Profi,
  1352. Hüthig Buch Verlag, Heidelberg (1990)
  1353. NVDI Sven Behne, Wilfried Behne, NVDI-Dokumentation, 
  1354. BELA
  1355.  
  1356. falcon Hendricks, Herzlinger, Pittelkow, Das Buch zum Atari Falcon030, 1. Auflage,
  1357. Data Becker, Düsseldorf (1992)
  1358. intern Bär, Bauder, Windows 3.1 intern, 1. Auflage,
  1359. Data Becker, Düsseldorf (1992)
  1360. tpwow Ertl, Machholz, TurboPascal für Windows - ObjectWindows,
  1361. SYBEX, Düsseldorf (1992)
  1362. borland1 BorlandPascal 7.0, ObjectWindows Programmierhandbuch,
  1363. Borland (1992)
  1364. borland2 Borland C++ 4.0, ObjectWindows Referenzhandbuch,
  1365. Borland (1993)
  1366. borland3 Paradox 4.0, PAL-Programmierhandbuch,
  1367. Borland (1992)
  1368. formate Günter Born, Referenzhandbuch Dateiformate, 2. Auflage, 
  1369. Addison-Wesley, Bonn (1992)
  1370.  
  1371. formate2 Günter Born, Dateiformate Programmierhandbuch, 
  1372. Addison-Wesley, Bonn (1993)
  1373.  
  1374. latex Helmut Kopka, : eine Einführung, 4. Auflage,
  1375. Addison-Wesley, Bonn (1992)
  1376.  
  1377. gkp Graham, Knuth, Patashnik, Concrete Mathematics, 7. Auflage,
  1378. Addison-Wesley (1991)
  1379. duden Hermann Engesser (Hrsg.), Duden Informatik, 2. Auflage,
  1380. Dudenverlag, Mannheim (1993)
  1381. kochen meine Familie & ich, Kochen & backen mit Obst,
  1382. Burda (1991)
  1383. adams Douglas Adams, Per Anhalter durch die Galaxis; Das
  1384. Restaurant am Ende des Universums; Das Leben, das Universum und der
  1385. ganze Rest; Macht's gut und danke für den Fisch; Dirk Gently's
  1386. Holistische Detektei, Der lange, dunkle Fünfuhrtee der Seele;
  1387. The Hitch Hiker's Guide to the Galaxy; The Restaurant at the End
  1388. of the Universe; Life, the Universe and Everything; So Long, and
  1389. Thanks for all the Fish; Mostly Harmless; Dirk Gently's holistic
  1390. Detective Agency; The long dark Tea-Time of the Soul; The Meaning
  1391. of Liff
  1392. tee Adrian, Temming, Vollers, Das Teebuch,
  1393. VMA Verlag, Wiesbaden (1989)
  1394. johnnie Walker, Red Label,
  1395. John Walker & Sons, Kilmarnock (Müller lebt!)
  1396. camouflage Camouflage, Bodega Bohemia,
  1397. Metronome (1993)
  1398. amos Tori Amos, Under the Pink,
  1399. eastwest (1994)
  1400. neworder New Order, Republic,
  1401. CentreDate (1993)
  1402.  
  1403.